package services

import (
	global "earth/global_data"
	mqtt "earth/mqtt"
	"encoding/json"
	"fmt"
	"log"
	"net"
	"strconv"
	"strings"
	"time"
)

// HandleConn 处理连接
func HandleConn(conn net.Conn, token string) {
	// 不间断的读取客户端发送的数据
	for {
		// 读取客户端发送的数据
		var buf [1024]byte
		n, err := conn.Read(buf[:])
		if err != nil {
			log.Println("Read() failed, err: ", err)
			conn.Close()
			return
		}
		// 将读取到的数据转为字符串
		data := string(buf[:n])
		err = dataHandleConn(data, token)
		if err != nil {
			log.Println("dataHandleConn() failed, err: ", err)
			// 失败响应
			return
		}
		// 成功响应
		successResponse(conn, token)
	}
}

// 处理单个连接
func dataHandleConn(data string, token string) error {

	// 解析数据包
	dataMap, err := parseData(data)
	if err != nil {
		log.Println("数据包解析错误：", err)
		return err
	}
	// 组装payload
	payloadMap := map[string]interface{}{
		"token": token,
	}
	var values []byte
	// 将payloadMap.values 转为json字符串
	values, err = json.Marshal(dataMap)
	if err != nil {
		log.Println("数据转换错误：", err)
		return err
	}
	log.Println("payloadMap.values:", string(values))
	payloadMap["values"] = values
	payload, err := json.Marshal(payloadMap)
	if err != nil {
		log.Println("数据转换错误：", err)
		return err
	}
	// 发布消息
	mqtt.Publish(string(payload))
	return nil
}

// 创建map映射通道类型
var channelTypeMap = map[string]string{
	"0": "None-N",
	"1": "Pressure-K",
	"2": "Pressure-M",
	"3": "Temperature-T",
	"4": "Temperature-F",
	"5": "LiquidLevel-H",
	"6": "LiquidLevel-L",
	"7": "Humidity-R",
	"8": "FlowRate-C",
	"9": "FlowRate-D",
	"A": "FlowSpeed-U",
	"B": "FlowSpeed-V",
	"C": "Switch-J",
	"D": "Frequency-G",
	"E": "NoneType-P",
	"F": "PH-Q",
}

//解析数据包
/*
0-2   2230359,898604A62621C0165128,30000000,
3-10  0.000,100.000,0.000,1.000,0.000,2.500,0.000,1.600,
11-18 0.000,2.500,0.000,2.500,0.000,2.500,0.000,2.500,
19-21 0,0,0,
22-29 04,06,47,20,FF,00,12.9,26,
30-37 -25.000,-0.250,0.000,0.000,0.000,0.000,0,0,
38 2015-08-03;08:32:00,
39-46 (-25.000;),(),(),(),(),(),(),(),
47-48 00000000,Request_ends!
*/
func parseData(data string) (map[string]float64, error) {
	// 数据位在报文的30-37位，逗号分隔
	dataList := strings.Split(data, ",")
	if len(dataList) < 49 {
		log.Println("数据包格式错误：", data)
		return nil, fmt.Errorf("数据包格式错误")
	}
	// 通道类型是第三位
	dataTypeStr := dataList[2]
	// dataTypeStr长度不能小于8，按位分割
	dataTypeList := strings.Split(dataTypeStr, "")
	if len(dataTypeList) < 8 {
		log.Println("通道类型错误", dataTypeStr)
		return nil, fmt.Errorf("通道类型错误")
	}
	dataValueList := dataList[30:37]
	// 创建数据map
	dataMap := make(map[string]float64)
	// 遍历通道类型列表,按照通道类型用channelTypeMap映射，忽略为0的通道类型，并在将映射结果后加上通道的下标
	// 映射结果为dataMap的key，value为数据包中对应通道的数据.并将值转为float64
	for i, v := range dataTypeList {
		if v == "0" {
			continue
		}
		value := dataValueList[i]
		// 转为float64
		valueFloat64, err := strconv.ParseFloat(value, 64)
		if err != nil {
			log.Println("数据转换错误：", err)
			continue
		}
		// int转为string
		strI := strconv.Itoa(i)
		dataMap[channelTypeMap[v]+"-"+strI] = valueFloat64
	}
	return dataMap, nil
}

// 成功响应"*MS-NOSET#=time,REAL MESSAGE END!"
func successResponse(conn net.Conn, token string) {
	var err error
	// 判断ConfigMap是否为空
	if data, exists := ConfigMap[token]; exists {
		//判断data是否为空
		if data != "" {
			// 清空ConfigMap
			ConfigMap[token] = ""
			_, err = conn.Write([]byte(data))
			log.Println("发送配置信息：", data)
		} else {
			_, err = conn.Write([]byte("*MS-NOSET#=time,REAL MESSAGE END!"))
			log.Println("发送接收成功信息：*MS-NOSET#=time,REAL MESSAGE END!")
		}
	} else {
		_, err = conn.Write([]byte("*MS-NOSET#=time,REAL MESSAGE END!"))
		log.Println("发送接收成功信息：*MS-NOSET#=time,REAL MESSAGE END!")
	}
	if err != nil {
		log.Println("Write() failed, err: ", err)
		conn.Close()
		return
	}
}

/*
*MS-SET#=4,4,0,00,00,115.29.194.124:8080,
0.500,2.000,0.500,2.000,0.500,2.000,0.500,2.000,
200,800,000,000,000.000,000.000,0.500,2.000,
0.000,0.000,0.000,0.02,0.02,0.000,
00042000,1,2018-05-27;14:09:49,SET MESSAGE END!
*/
// 存储上次的设置值
func saveLastSetValues(dataList []string, token string) {
	// 初始化saveList
	var saveList [32]string
	saveList[0] = "*MS-SET#=" + dataList[19] //Sample_time
	saveList[1] = dataList[20]               // Send_time
	saveList[2] = dataList[21]               // Picture_time
	saveList[3] = dataList[26]               // Ctrl_Word
	saveList[4] = dataList[27]               // Ctrl_Word
	// saveList[5] = ""                         // IP:PORT

	// saveList[6] = "0.500"  // 第一...第八通道阈值下限
	// saveList[7] = "2.000"  // 第一...第八通道阈值下限
	// saveList[8] = "0.500"  // 第一...第八通道阈值下限
	// saveList[9] = "2.000"  // 第一...第八通道阈值下限
	// saveList[10] = "0.500" // 第一...第八通道阈值下限
	// saveList[11] = "2.000" // 第一...第八通道阈值下限
	// saveList[12] = "0.500" // 第一...第八通道阈值下限
	// saveList[13] = "2.000" // 第一...第八通道阈值下限

	// saveList[14] = "200"     // 第一...第八通道阈值上限
	// saveList[15] = "800"     // 第一...第八通道阈值上限
	// saveList[16] = "000"     // 第一...第八通道阈值上限
	// saveList[17] = "000"     // 第一...第八通道阈值上限
	// saveList[18] = "000.000" // 第一...第八通道阈值上限
	// saveList[19] = "000.000" // 第一...第八通道阈值上限
	// saveList[20] = "0.500"   // 第一...第八通道阈值上限
	// saveList[21] = "2.000"   // 第一...第八通道阈值上限

	// saveList[22] = "0.000" // 第一...第六通道波动值
	// saveList[23] = "0.000" // 第一...第六通道波动值
	// saveList[24] = "0.000" // 第一...第六通道波动值
	// saveList[25] = "0.02"  // 第一...第六通道波动值
	// saveList[26] = "0.02"  // 第一...第六通道波动值
	// saveList[27] = "0.000" // 第一...第六通道波动值

	saveList[28] = dataList[47] // 告警阈值
	// saveList[29] = ""                    // setHistory 历史存储方式
	// saveList[30] = "2016-05-04;15:02:01" //  服务器返回时间，用以设备时间校准时间格式 2017-12-31;12:00:00
	// saveList[31] = "SET MESSAGE END!"
	LastPushMap[token] = saveList[:]
}

/*
	saveList[6] = "0.500"  // 第一...第八通道阈值下限
	saveList[7] = "2.000"  // 第一...第八通道阈值下限
	saveList[8] = "0.500"  // 第一...第八通道阈值下限
	saveList[9] = "2.000"  // 第一...第八通道阈值下限
	saveList[10] = "0.500" // 第一...第八通道阈值下限
	saveList[11] = "2.000" // 第一...第八通道阈值下限
	saveList[12] = "0.500" // 第一...第八通道阈值下限
	saveList[13] = "2.000" // 第一...第八通道阈值下限

	saveList[14] = "200"     // 第一...第八通道阈值上限
	saveList[15] = "800"     // 第一...第八通道阈值上限
	saveList[16] = "000"     // 第一...第八通道阈值上限
	saveList[17] = "000"     // 第一...第八通道阈值上限
	saveList[18] = "000.000" // 第一...第八通道阈值上限
	saveList[19] = "000.000" // 第一...第八通道阈值上限
	saveList[20] = "0.500"   // 第一...第八通道阈值上限
	saveList[21] = "2.000"   // 第一...第八通道阈值上限

	saveList[22] = "0.000" // 第一...第六通道波动值
	saveList[23] = "0.000" // 第一...第六通道波动值
	saveList[24] = "0.000" // 第一...第六通道波动值
	saveList[25] = "0.02"  // 第一...第六通道波动值
	saveList[26] = "0.02"  // 第一...第六通道波动值
	saveList[27] = "0.000" // 第一...第六通道波动值
*/

// 处理配置
func HandleConfig(DeviceConfig global.DeviceConfig) error {
	var lastPushFlag bool
	// 判断LastPushMap是否为空
	var lastPushList []string
	if lpList, exists := LastPushMap[DeviceConfig.AccessToken]; exists {
		// 判断lastPushList长度是否为49
		if len(lpList) != 32 {
			log.Println("上次推送的设置字段不为49:", lpList)
			lastPushFlag = false
		}
		lastPushList = lpList
		lastPushFlag = true
	} else {
		lastPushFlag = false
	}
	var commandList [32]string
	// Sample_time
	commandList[0] = "*MS-SET#=" + DeviceConfig.SampleTime
	// Send_time
	commandList[1] = DeviceConfig.SendTime
	// Picture_time
	commandList[2] = DeviceConfig.PictureTime
	// Ctrl_Word
	// 如果DeviceConfig.CtrlWord为空，从lastPushMap中取出上次的设置
	if DeviceConfig.CtrlWord == "" {
		if lastPushFlag {
			commandList[3] = lastPushList[3] // Ctrl_Word
			commandList[4] = lastPushList[4] // Ctrl_Word
		} else {
			log.Println("Ctrl_Word为空，且上次推送的设置不存在")
			return fmt.Errorf("Ctrl_Word为空，且上次推送的设置不存在")
		}
	} else {
		commandList[3] = DeviceConfig.CtrlWord
		// Ctrl_Word
		commandList[4] = DeviceConfig.CtrlWord
	}

	// IP:PORT
	if DeviceConfig.IPPORT == "" {
		if lastPushFlag {
			commandList[5] = lastPushList[5] // IP:PORT
		} else {
			log.Println("IP:PORT为空，且上次推送的设置不存在")
			return fmt.Errorf("IP:PORT为空，且上次推送的设置不存在")
		}
	} else {
		//校验IP:PORT格式
		ipPortList := strings.Split(DeviceConfig.IPPORT, ":")
		if len(ipPortList) < 2 {
			log.Println("IP:PORT格式错误：", DeviceConfig.IPPORT)
			return fmt.Errorf("IP:PORT格式错误")
		}
		commandList[5] = DeviceConfig.IPPORT
	}
	// 第一...第八通道阈值下限,逗号分割DeviceConfig.ThresholdLower
	thresholdLowerList := strings.Split(DeviceConfig.ThresholdLower, ",")
	if len(thresholdLowerList) < 8 {
		log.Println("ThresholdLower格式错误：", DeviceConfig.ThresholdLower)
		return fmt.Errorf("ThresholdLower格式错误")
	}
	commandList[6] = thresholdLowerList[0]
	commandList[7] = thresholdLowerList[1]
	commandList[8] = thresholdLowerList[2]
	commandList[9] = thresholdLowerList[3]
	commandList[10] = thresholdLowerList[4]
	commandList[11] = thresholdLowerList[5]
	commandList[12] = thresholdLowerList[6]
	commandList[13] = thresholdLowerList[7]
	// 第一...第八通道阈值上限,逗号分割DeviceConfig.ThresholdUpper
	thresholdUpperList := strings.Split(DeviceConfig.ThresholdUpper, ",")
	if len(thresholdUpperList) < 8 {
		log.Println("ThresholdUpper格式错误：", DeviceConfig.ThresholdUpper)
		return fmt.Errorf("ThresholdUpper格式错误")
	}
	commandList[14] = thresholdUpperList[0]
	commandList[15] = thresholdUpperList[1]
	commandList[16] = thresholdUpperList[2]
	commandList[17] = thresholdUpperList[3]
	commandList[18] = thresholdUpperList[4]
	commandList[19] = thresholdUpperList[5]
	commandList[20] = thresholdUpperList[6]
	commandList[21] = thresholdUpperList[7]
	// 第一...第六通道波动值,逗号分割DeviceConfig.Wave
	waveList := strings.Split(DeviceConfig.Wave, ",")
	if len(waveList) < 6 {
		log.Println("Wave格式错误：", DeviceConfig.Wave)
		return fmt.Errorf("Wave格式错误")
	}
	commandList[22] = waveList[0]
	commandList[23] = waveList[1]
	commandList[24] = waveList[2]
	commandList[25] = waveList[3]
	commandList[26] = waveList[4]
	commandList[27] = waveList[5]
	// 告警阈值
	if DeviceConfig.WarnMode == "" {
		if lastPushFlag {
			commandList[28] = lastPushList[28] // 告警阈值
		} else {
			log.Println("告警阈值为空，且上次推送的设置不存在")
			return fmt.Errorf("告警阈值为空，且上次推送的设置不存在")
		}
	} else {
		//校验告警阈值格式编码格式 00000000~77777733
		if len(DeviceConfig.WarnMode) != 8 {
			log.Println("告警阈值格式错误：", DeviceConfig.WarnMode)
			return fmt.Errorf("告警阈值格式错误")
		}
		commandList[28] = DeviceConfig.WarnMode
	}
	// setHistory 历史存储方式
	commandList[29] = DeviceConfig.SetHistory
	// 服务器返回时间，用以设备时间校准时间格式 2017-12-31;12:00:00
	nowTime := time.Now().Format("2006-01-02;15:04:05")
	commandList[30] = nowTime
	commandList[31] = "SET MESSAGE END!"
	// 将commandList转为字符串用逗号分隔
	commandStr := strings.Join(commandList[:], ",")
	// 将commandStr转为[]byte
	// 将command写入ConfigMap
	ConfigMap[DeviceConfig.AccessToken] = commandStr
	log.Println("commandStr:", commandStr)
	return nil
}
